# -*- coding: utf-8 -*-
'''
  Description：获取eureka上注册服务相关数据
  Author：zhanghaisheng
  Date：2021.10.22
'''
# import os
import re
import requests
import time
from xml.dom.minidom import parse, parseString

class EurekaManage():

    def __init__(self, eureka_addr='', server_name=''):
        self.eureka_addr = eureka_addr
        self.server_name = server_name
        # res = requests.get(self.eureka_addr)
        # self.dom = parseString(res.text)
        self.app = self.get_app(self.server_name)
        # print("#"*50)
        # print(f"server_name: {server_name}")
        # print("#"*50)
        # from code import interact
        # interact(local=locals())

    # def get_eureka_data(self, eureka_addr, dest_path):
    #     '''
    #       获取euraka整体数据并保存成xml文件
    #       eureka_addr为 eureka地址，如：http://10.43.75.132:13001/eureka/apps
    #       dest_path为保存文件地址，如：/opt/eureka.xml
    #     '''
    #     os.popen('curl ' + eureka_addr + ' > ' + dest_path)

    def get_server_status(self):
        '''
          获取服务状态
          eureka_xml_path为 eureka文件地址，如：/opt/eureka.xml
          server_name需要查询的服务名称，如：IMP-PC-SERVICE，支持大小写
        '''
        # app = self.get_app(eureka_xml_path, server_name)
        app = self.app
        if app is None:
            return []
        else:
            instances = app.getElementsByTagName('instance')
            status = []
            for instance in instances:
                status.append(instance.getElementsByTagName("status")[0].firstChild.data)
            status = list(set(status))
            return status

    def get_server_version(self):
        '''
          获取服务版本号
          eureka_xml_path为 eureka文件地址，如：/opt/eureka.xml
          server_name需要查询的服务名称，如：IMP-PC-SERVICE，支持大小写
        '''
        # app = self.get_app(eureka_xml_path, server_name)
        app = self.app
        if app is None:
            return []
        else:
            instances = app.getElementsByTagName('instance')
            version_info = []
            for instance in instances:
                regist_timestamp = (instance.getElementsByTagName("leaseInfo")[0]).getElementsByTagName("registrationTimestamp")[0].firstChild.data
                if regist_timestamp:
                    regist_timestamp = int(regist_timestamp[0:10]) if len(regist_timestamp) > 10 else int(regist_timestamp)
                    regist_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(regist_timestamp))
                    print("regist time is " + regist_time)
                else:
                    regist_time = ''
                instance_id = instance.getElementsByTagName("instanceId")[0].firstChild.data
                data_list = instance_id.split(':')
                if data_list[-1].isdigit() or bool(re.search(r'\d', data_list[-1])) is False:  # 判断冒号切割最后一位如果是纯数字或纯文本
                    version_info.append('no_version_code' + '(' + regist_time + ')')
                else:
                    only_text = ''
                    port = ''
                    for data in data_list:
                        if data.isdigit():  # 判断是否是纯数字，即端口号
                            port = data
                            version_info.append(instance_id.split(data + ':')[1] + '(' + regist_time + ')')
                            break
                        elif bool(re.search(r'\d', data)) is False:  # 判断是否不包含数字，即服务名
                            only_text = data
                    if port != '':
                        version_info.append(instance_id.split(port + ':')[1] + '(' + regist_time + ')')
                    else:
                        version_info.append(instance_id.split(only_text + ':')[1] + '(' + regist_time + ')')
            version_info = list(set(version_info))
            if version_info is None:
                print('sever: ' + self.server_name + ' version_info is None!')
                return []
            else:
                return version_info

    def get_registed_ip(self):
        '''
          获取服务注册ip
          eureka_xml_path为 eureka文件地址，如：/opt/eureka.xml
          server_name需要查询的服务名称，如：IMP-PC-SERVICE，支持大小写
        '''
        # app = self.get_app(eureka_xml_path, server_name)
        app = self.app
        if app is None:
            return None
        else:
            instances = app.getElementsByTagName('instance')
            ip_info = []
            for instance in instances:
                instance_id = instance.getElementsByTagName("instanceId")[0].firstChild.data
                data_list = instance_id.split(':')
                ip_info.append(data_list[0])
            ip_info = list(set(ip_info))
            if ip_info is None:
                print('sever: ' + self.server_name + ' ip_info is None!')
                return None
            else:
                return ip_info

    def get_app(self, server_name):
        '''
          获取一个app对象，app即一个服务对象，包含app全部注册信息
          eureka_xml_path为 eureka文件地址，如：/opt/eureka.xml
          server_name需要查询的服务名称，如：IMP-PC-SERVICE，支持大小写
        '''
        # if os.path.exists(eureka_xml_path) is False:
        #     print('eureka.xml not exist!')
        #     return None
        # domTree = parseString(self)(eureka_xml_path)
        for i in range(0, 10):
            res = requests.get(self.eureka_addr)
            domTree = parseString(res.text)
            if domTree is None:
                print('no eureka data!')
                continue
            else:
                rootNode = domTree.documentElement
                apps = rootNode.getElementsByTagName('application')
                if apps is None:
                    print('no registed apps!')
                    continue
                for app in apps:
                    if server_name.upper() in app.getElementsByTagName("name")[0].firstChild.data.upper():
                        print("find app " + app.getElementsByTagName("name")[0].firstChild.data)
                        return app
            print(server_name.upper() + " not find, wait 6 seconds and get eureka regist message again!")
            time.sleep(6)
        print(server_name.upper() + ' not registed success in 1 minute!')
        return None